#include "atheme.h"

DECLARE_MODULE_V1
(
	"chanserv/akick_autosync", false, _modinit, _moddeinit,
	PACKAGE_STRING,
	"Alexey Chernov-Phoenix <phoenix -at- pravmail.ru>"
);

static void
on_channel_akick_add(chanacs_t *data)
{
	chanuser_t *cu;
	mychan_t *mc = data->mychan;
	node_t *n, *tn;

	user_t *u;
	channel_t *chan;
	unsigned int flags;
	metadata_t *md;
	chanacs_t *ca2;
	char akickreason[120] = "User is banned from this channel", *p;

	if (metadata_find(mc, "private:botserv:bot-assigned") != NULL)
		return;
	
	if (!mc || !mc->chan || !mc->chan->nummembers)
	    return;

	LIST_FOREACH_SAFE(n, tn, mc->chan->members.head)
	{
		cu = (chanuser_t *)n->data;
		u = cu->user;
		chan = cu->chan;

		if (is_internal_client(cu->user))
			continue;

		flags = chanacs_user_flags(mc, u);

		if (flags & CA_AKICK && !(flags & CA_REMOVE))
		{
			/* Stay on channel if this would empty it -- jilles */
			if (chan->nummembers <= (mc->flags & MC_GUARD ? 2 : 1))
			{
				mc->flags |= MC_INHABIT;
				if (!(mc->flags & MC_GUARD))
					join(chan->name, chansvs.nick);
			}
			/* use a user-given ban mask if possible -- jilles */
			ca2 = chanacs_find_host_by_user(mc, u, CA_AKICK);
			if (ca2 != NULL)
			{
				if (chanban_find(chan, ca2->host, 'b') == NULL)
				{
					char str[512];

					chanban_add(chan, ca2->host, 'b');
					snprintf(str, sizeof str, "+b %s", ca2->host);
					/* ban immediately */
					mode_sts(chansvs.nick, chan, str);
				}
			}
			else
			{
				/* XXX this could be done more efficiently */
				ca2 = chanacs_find(mc, u->myuser, CA_AKICK);
				ban(chansvs.me->me, chan, u);
			}
			remove_ban_exceptions(chansvs.me->me, chan, u);
			if (ca2 != NULL)
			{
				md = metadata_find(ca2, "reason");
				if (md != NULL && *md->value != '|')
				{
					snprintf(akickreason, sizeof akickreason,
							 "Banned: %s", md->value);
					p = strchr(akickreason, '|');
					if (p != NULL)
						*p = '\0';
					else
						p = akickreason + strlen(akickreason);
					/* strip trailing spaces, so as not to
					 * disclose the existence of an oper reason */
					p--;
					while (p > akickreason && *p == ' ')
						p--;
					p[1] = '\0';
				}
			}
			try_kick(chansvs.me->me, chan, u, akickreason);
			return;
		}
	}
}

void _modinit(module_t *m)
{
	hook_add_event("channel_akick_add");
	hook_add_channel_akick_add(on_channel_akick_add);
}

void _moddeinit(void)
{
	hook_del_channel_akick_add(on_channel_akick_add);
}
